(* Type Caml representant un atelier *)
(* Projet L3 INFO 2009/2010 *)

(* Bourigault Simon, Tcha-Tokey Katy, Canezin Floriant *)

type prix = Prix of float ;;					(* Type permettant de typer au maximum les donnees *)

type duree = Duree of float ;;					(* Type permettant de typer au maximum les donnees *)


(* Definitions des pieces *)
(* Version abstraite *)
type categorie = Categorie of string ;;				(* libelle d'une piece *)
(* Version concrete *)
type piece = 
	Piece_achetee of categorie * prix			(* Une piece achetee est caracterisee par sa categorie et son prix *)
	|Piece_fabriquee of categorie * montage			(* Une piece fabriquee est caracterisee par sa categoris et le montage permmetant de l'obtenir *)
	
(* Definition d'une etape/operation *)
(* Version abstraite *)
and operation = Operation of string * duree * prix * categorie list 	(* Nom, duree, prix, categories neccessaire *)
(* Version concrete *)
and etape = Etape of operation * piece list			(* Applique a une liste de piece, devant correspondre aux categories de l'operation *)


(* Definition d'une gamme/montage *)
(* Version abstraite *)
and gamme = Gamme of operation list
(* Vesion concrete *)				
and montage = Montage of etape list


and stock = Stock of piece list

and atelier = Atelier of gamme list * prix * stock ;;		(* gammes, cout horaire, liste des pieces disponibles *)
								(* Cette fois, on fait bien la distinction entre les pieces que l'atelier achete et fabrique lui-meme *)



(******************************************************************************)


(* getPrix : prix -> float *)
(* Renvoie le prix en float *)
let getPrix = fun (Prix x) -> x ;;

(* getPrix : duree -> float *)
(* Renvoie la duree en float *)
(* On considère que l'on manipule des heures *)
let getDuree = fun (Duree x) -> x ;;

(* getCategorie : piece -> categorie *)
(* Renvoie la catégorie d'une piece *)
let getCategorie =
	function Piece_achetee(c,_)->c
		|Piece_fabriquee(c,_)->c ;;

(* getCategorieResultante : operation -> categorie *)
(* Renvoie la piece produite par cette etape.
Par convention, il s'agit de la première categorie de la liste *)
let getCategorieResultante =
	function Operation(_,_,_,c::_)-> c
		|Operation(_,_,_,[]) -> failwith("Pas de catégorie résultante") ;;


(******************************************************************************)


(* dureeMontage : montage->duree *)
(* Calcule la duree d'un montage *)
let rec dureeMontage =
	function Montage([]) -> Duree(0.0)
		|Montage(Etape(Operation(_,Duree(x),_,_),_)::r) -> Duree(x+.getDuree(dureeMontage (Montage r))) ;; 

(* dureeGamme : gamme->duree *)
(* Calcule la duree d'une gamme *)
let rec dureeGamme = 
	function Gamme([]) -> Duree(0.0)
		|Gamme(Operation(_,Duree(x),_,_)::r) -> Duree(x+.getDuree(dureeGamme (Gamme r))) ;;
(* dureeGamme(Gamme([Operation("alpha",Duree(1.0),Prix(200.0),[Categorie("truc")]);Operation("beta",Duree(2.0),Prix(300.0),[Categorie("machin")])])) ;; *)

(* prixGamme : gamme->prix->prix *)
(* Calcule le prix d'une gamme en fonction d'un coût horaire donné *)
let prixGamme = fun gamme coutH -> Prix((getDuree(dureeGamme gamme))*.(getPrix coutH)) ;;

(* dureeStock : atelier->duree *)
(* Calcul le temps necessaire pour fabrique toute les piece_fabriquee d'un atelier *)
let rec dureeStock =
	function Atelier(_,_,Stock []) -> Duree(0.0)
		|Atelier(nom,coutH,Stock(Piece_achetee(_,_)::r)) -> dureeStock(Atelier(nom,coutH,Stock r))
		|Atelier(nom,coutH,Stock(Piece_fabriquee(_,mntg)::r)) -> Duree((getDuree (dureeMontage mntg)) +. getDuree(dureeStock(Atelier(nom,coutH,Stock(r))))) ;;








(*******************************************************************************************************)
(***** CALCUL DU PRIX MINIMAL DE PRODUCTION  (certaines fonctions doivent etre definies ensemble)  *****)

(* suiviEtape: piece list->atelier->string list *)
(* determine le suivi de fabrication ou achat des pieces necessaires a 1 etape *)
let rec suiviEtape=
	function [] -> fun a -> []
			|p::l -> fun a -> (snd(prixMinPiece (getCategorie p) a)) @(suiviEtape l a)

and
(* suiviMontage: Montage->atelier->string list *)
(* renvoi la liste des noms des operations a operer *)
  suiviMontage=
	function (Montage([])) -> fun a -> []
			|(Montage(Etape(Operation(n,_,_,_),pl)::l)) -> fun a -> (suiviEtape pl a)@(("faire "^n)::(suiviMontage (Montage(l)) a))

and
(* prixMinOp: etape->prix *)
(* calcule le prix minimal de l'etape en fonction du cout horaire de l'atelier *)
  prixMinOp = fun (Etape(o, pl)) (Atelier(g,cH,Stock s)) ->
	(match o with
		(* cas ou il ne faut pas de pieces *)
		 (Operation(_,d,px,[])) -> Prix(getDuree(d)*.getPrix(cH)+.getPrix(px))
		(* cas ou il en faut *) 
		|(Operation(_,d,px,c::lc)) ->
			let aux=List.fold_right( fun c r -> getPrix(fst (prixMinPiece c (Atelier(g,cH,Stock s))))+.r ) (c::lc) 0.
			in
			Prix(getDuree(d)*.getPrix(cH)+.getPrix(px)+.aux)
	)

and

(* prixMinMontage: montage->prix->prix * string list *)
(* calcule le prix minimal du montage en fonction du cout horaire de l'atelier *)
prixMinMontage=fun (Montage(el)) a ->
	( (match el with
		 [] -> Prix(0.)
		|(e::l) -> Prix(getPrix(fst (prixMinMontage (Montage(l)) a))+.getPrix(prixMinOp e a)) 	
	  ), (suiviMontage (Montage(el)) a) )
and

(* prixMinPiece : categorie->atelier->prix * string list *)
(* calcule le prix minimal de la piece en fonction de l'atelier *)
prixMinPiece = fun (Categorie c) a ->
	(let rec aux1_prix=   (* determine tous les prix et suivis pour cette categorie *)
		function (Categorie c), Atelier(g,cH,Stock(Piece_achetee(c1,p)::r)), res ->
					if ((Categorie c)=c1) then aux1_prix((Categorie c), Atelier(g,cH,Stock r), (p,["achat "^c^" au prix de "^string_of_float(getPrix(p))])::res)
					else aux1_prix((Categorie c), Atelier(g,cH,Stock r), res)
				|(Categorie c), Atelier(g,cH,Stock(Piece_fabriquee(c1, mntg)::r)), res ->
					if ((Categorie c)=c1) then aux1_prix((Categorie c), Atelier(g,cH,Stock r), (prixMinMontage mntg a)::res)
					else aux1_prix((Categorie c), Atelier(g,cH,Stock r), res)
				|_,Atelier(_,_,Stock []), res -> res
	 in
	 let rec aux2_min =   (* determine le plus petit *)
		function [p] -> p
				|p1::p2::l -> aux2_min((if (getPrix(fst p1)<getPrix(fst p2)) then p1 else p2)::l)
				|_->failwith("impossible d'obtenir cette piece")
	 in
	 aux2_min(aux1_prix((Categorie c),a,[]))
	)
	
	;;
	







	
(****************************************************************************************)


(* prixStock : atelier->prix *)
(* Calcule le prix du stock d'un atelier, en tenant compte des coup de fabrication ou d'achat des pieces *)
let prixStock = function Atelier(g,c,s) ->
	let rec aux= fun a ->
		function Stock([]) -> Prix(0.0)
				|Stock(Piece_achetee(_,p)::r) -> Prix(getPrix(p)+.getPrix((aux a (Stock r))))
				|Stock(Piece_fabriquee(_,mntg)::r) -> Prix(getPrix(fst( prixMinMontage mntg a))+.getPrix((aux a (Stock r))))
	in aux (Atelier(g,c,s)) s;;

(* pieceMinPrix : piece->piece->atelier->piece *)
(* Renvoi la piece dont le prix est le plus petit parmis les 2 proposees dan l'atelier considere *)
let pieceMinPrix = fun p1 p2 a->
	match (p1,p2) with
		 Piece_achetee(_,px1),Piece_achetee(_,px2) -> if getPrix(px1)<getPrix(px2) then p1 else p2
		|Piece_achetee(_,px1),Piece_fabriquee(_,mntg2) -> if getPrix(px1)<getPrix(fst (prixMinMontage mntg2 a)) then p1 else p2
		|Piece_fabriquee(_,mntg1),Piece_achetee(_,px2) -> if getPrix(fst(prixMinMontage mntg1 a))<getPrix(px2) then p1 else p2
		|Piece_fabriquee(_,mntg1),Piece_fabriquee(_,mntg2) -> if getPrix(fst(prixMinMontage mntg1 a))<getPrix(fst(prixMinMontage mntg2 a)) then p1 else p2








(***************************************************)
(********** FONCTIONS DE TEST DE VALIDITE **********)

(* valideEtape:Etape->bool *)
(* verifie que les pieces specifiees par l'etapes conviennent a l'operation *)
let rec valideEtape = fun (Etape((Operation(n,d,p,lc)),lp)) ->
	match lc with
		 [] -> if (lp=[]) then true else false
		|lc -> if (lp=[]) then false else (getCategorie(List.hd lp)=(List.hd(lc))&& (valideEtape (Etape((Operation(n,d,p,(List.tl lc))),(List.tl lp)))));;
		








(***************************************************************)
(******************** EXAMPLES D'ATELIER    ********************)

let monAtelier=Atelier([Gamme([Operation("op1",Duree(2.3),Prix(0.),[Categorie("p1");Categorie("p2")])])], Prix(120.),
						Stock([ Piece_achetee(Categorie("p1"),Prix(100.));
						 Piece_achetee(Categorie("p2"),Prix(80.));
						 Piece_achetee(Categorie("p3"),Prix(8000.));
						 Piece_fabriquee(Categorie("p3"),
						 		Montage([ Etape( Operation("op1",Duree(2.3),Prix(0.),[Categorie("p1");Categorie("p2")]) ,
						 					[ Piece_achetee(Categorie("p1"),Prix(100.));
						 					  Piece_achetee(Categorie("p2"),Prix(80.))
						 					])
						 				]
						 		)
						 )
						])
					  );;


(* attention, tres long ^^ *)
let a5=Atelier([Gamme([])], Prix(100.),
			   Stock([ Piece_achetee(Categorie("p1"),Prix(100.));
			   	Piece_achetee(Categorie("p2"),Prix(80.));
			   	Piece_achetee(Categorie("p3"),Prix(8000.));
			   	Piece_achetee(Categorie("p4"),Prix(80.));
			   	
			   	(* differentes possibilites avec operation: complicatedoperation *)			   	
			   	Piece_fabriquee(Categorie("computer"),
			   			Montage([ Etape( Operation("complicatedoperation", Duree(4.5), Prix(0.),[Categorie("p1");Categorie("p2");Categorie("p3");Categorie("p4")]) ,
			   						[ Piece_achetee(Categorie("p1"),Prix(100.));
			   						  Piece_achetee(Categorie("p2"),Prix(80.));
			   						  Piece_achetee(Categorie("p3"),Prix(8000.));
			   						  Piece_achetee(Categorie("p4"),Prix(80.))
			   						]
			   					  )
			   					]
			   			)
			   	);
			   	Piece_fabriquee(Categorie("computer"),
			   			Montage([ Etape( Operation("complicatedoperation", Duree(4.5), Prix(0.),[Categorie("p1");Categorie("p2");Categorie("p3");Categorie("p4")]) ,
			   						[ Piece_fabriquee(Categorie("p1"),
			   								Montage([ Etape( Operation("op2", Duree(0.2), Prix(0.),[Categorie("p2")]) ,
								   						[ Piece_achetee(Categorie("p2"),Prix(80.))
								   						]
								  					  )
								  					]
								  			)
			   						  );
			   						  Piece_achetee(Categorie("p2"),Prix(80.));
			   						  Piece_achetee(Categorie("p3"),Prix(8000.));
			   						  Piece_achetee(Categorie("p4"),Prix(80.))
			   						]
			   					  )
			   					]
			   			)
			   	);
			   	Piece_fabriquee(Categorie("computer"),
			   			Montage([ Etape( Operation("complicatedoperation", Duree(4.5), Prix(0.),[Categorie("p1");Categorie("p2");Categorie("p3");Categorie("p4")]) ,
			   						[ Piece_achetee(Categorie("p1"),Prix(100.));
			   						  Piece_achetee(Categorie("p2"),Prix(80.));
			   						  Piece_fabriquee(Categorie("p3"),
			   						  		Montage([ Etape( Operation("op1", Duree(2.3), Prix(0.),[Categorie("p1");Categorie("p2")]) ,
								   						[ Piece_achetee(Categorie("p1"),Prix(100.));
								   						  Piece_achetee(Categorie("p2"),Prix(80.))
								   						]
								  					  );
								  					  Etape( Operation("op5", Duree(0.1), Prix(0.),[Categorie("p1");Categorie("p2")]) ,
								   						[ Piece_achetee(Categorie("p1"),Prix(100.));
								   						  Piece_achetee(Categorie("p2"),Prix(80.))
								   						]
								  					  )
								  					]
								  			)
			   						  );
			   						  Piece_achetee(Categorie("p4"),Prix(80.))
			   						]
			   					  )
			   					]
			   			)
			   	);
			   	Piece_fabriquee(Categorie("computer"),
			   			Montage([ Etape( Operation("complicatedoperation", Duree(4.5), Prix(0.),[Categorie("p1");Categorie("p2");Categorie("p3");Categorie("p4")]) ,
			   						[ Piece_achetee(Categorie("p1"),Prix(100.));
			   						  Piece_achetee(Categorie("p2"),Prix(80.));
			   						  Piece_fabriquee(Categorie("p3"),
			   						  		Montage([ Etape( Operation("op1", Duree(2.3), Prix(0.),[Categorie("p1");Categorie("p2")]) ,
								   						[ Piece_fabriquee(Categorie("p1"),
								   								Montage([ Etape( Operation("op2", Duree(0.2), Prix(0.),[Categorie("p2")]) ,
													   						[ Piece_achetee(Categorie("p2"),Prix(80.))
													   						]
													  					  )
													  					]
													  			)
								   						  );
								   						  Piece_achetee(Categorie("p2"),Prix(80.))
								   						]
								  					  );
								  					  Etape( Operation("op5", Duree(0.1), Prix(0.),[Categorie("p1");Categorie("p2")]) ,
								   						[ Piece_achetee(Categorie("p1"),Prix(100.));
								   						  Piece_achetee(Categorie("p2"),Prix(80.))
								   						]
								  					  )
								  					]
								  			)
			   						  );
			   						  Piece_achetee(Categorie("p4"),Prix(80.))
			   						]
			   					  )
			   					]
			   			)
			   	);
			   	Piece_fabriquee(Categorie("computer"),
			   			Montage([ Etape( Operation("complicatedoperation", Duree(4.5), Prix(0.),[Categorie("p1");Categorie("p2");Categorie("p3");Categorie("p4")]) ,
			   						[ Piece_achetee(Categorie("p1"),Prix(100.));
			   						  Piece_achetee(Categorie("p2"),Prix(80.));
			   						  Piece_fabriquee(Categorie("p3"),
			   						  		Montage([ Etape( Operation("op1", Duree(2.3), Prix(0.),[Categorie("p1");Categorie("p2")]) ,
								   						[ Piece_achetee(Categorie("p1"),Prix(100.));
								   						  Piece_achetee(Categorie("p2"),Prix(80.))
								   						]
								  					  );
								  					  Etape( Operation("op5", Duree(0.1), Prix(0.),[Categorie("p1");Categorie("p2")]) ,
								   						[ Piece_fabriquee(Categorie("p1"),
								   								Montage([ Etape( Operation("op2", Duree(0.2), Prix(0.),[Categorie("p2")]) ,
													   						[ Piece_achetee(Categorie("p2"),Prix(80.))
													   						]
													  					  )
													  					]
													  			)
								   						  );
								   						  Piece_achetee(Categorie("p2"),Prix(80.))
								   						]
								  					  )
								  					]
								  			)
			   						  );
			   						  Piece_achetee(Categorie("p4"),Prix(80.))
			   						]
			   					  )
			   					]
			   			)
			   	);
			   	Piece_fabriquee(Categorie("computer"),
			   			Montage([ Etape( Operation("complicatedoperation", Duree(4.5), Prix(0.),[Categorie("p1");Categorie("p2");Categorie("p3");Categorie("p4")]) ,
			   						[ Piece_achetee(Categorie("p1"),Prix(100.));
			   						  Piece_achetee(Categorie("p2"),Prix(80.));
			   						  Piece_fabriquee(Categorie("p3"),
			   						  		Montage([ Etape( Operation("op1", Duree(2.3), Prix(0.),[Categorie("p1");Categorie("p2")]) ,
								   						[ Piece_fabriquee(Categorie("p1"),
								   								Montage([ Etape( Operation("op2", Duree(0.2), Prix(0.),[Categorie("p2")]) ,
													   						[ Piece_achetee(Categorie("p2"),Prix(80.))
													   						]
													  					  )
													  					]
													  			)
								   						  );
								   						  Piece_achetee(Categorie("p2"),Prix(80.))
								   						]
								  					  );
								  					  Etape( Operation("op5", Duree(0.1), Prix(0.),[Categorie("p1");Categorie("p2")]) ,
								   						[ Piece_fabriquee(Categorie("p1"),
								   								Montage([ Etape( Operation("op2", Duree(0.2), Prix(0.),[Categorie("p2")]) ,
													   						[ Piece_achetee(Categorie("p2"),Prix(80.))
													   						]
													  					  )
													  					]
													  			)
								   						  );
								   						  Piece_achetee(Categorie("p2"),Prix(80.))
								   						]
								  					  )
								  					]
								  			)
			   						  );
			   						  Piece_achetee(Categorie("p4"),Prix(80.))
			   						]
			   					  )
			   					]
			   			)
			   	);
			   	Piece_fabriquee(Categorie("computer"),
			   			Montage([ Etape( Operation("complicatedoperation", Duree(4.5), Prix(0.),[Categorie("p1");Categorie("p2");Categorie("p3");Categorie("p4")]) ,
			   						[ Piece_fabriquee(Categorie("p1"),
			   								Montage([ Etape( Operation("op2", Duree(0.2), Prix(0.),[Categorie("p2")]) ,
								   						[ Piece_achetee(Categorie("p2"),Prix(80.))
								   						]
								  					  )
								  					]
								  			)
			   						  );
			   						  Piece_achetee(Categorie("p2"),Prix(80.));
			   						  Piece_fabriquee(Categorie("p3"),
			   						  		Montage([ Etape( Operation("op1", Duree(2.3), Prix(0.),[Categorie("p1");Categorie("p2")]) ,
								   						[ Piece_achetee(Categorie("p1"),Prix(100.));
								   						  Piece_achetee(Categorie("p2"),Prix(80.))
								   						]
								  					  );
								  					  Etape( Operation("op5", Duree(0.1), Prix(0.),[Categorie("p1");Categorie("p2")]) ,
								   						[ Piece_achetee(Categorie("p1"),Prix(100.));
								   						  Piece_achetee(Categorie("p2"),Prix(80.))
								   						]
								  					  )
								  					]
								  			)
			   						  );
			   						  Piece_achetee(Categorie("p4"),Prix(80.))
			   						]
			   					  )
			   					]
			   			)
			   	);
			   	Piece_fabriquee(Categorie("computer"),
			   			Montage([ Etape( Operation("complicatedoperation", Duree(4.5), Prix(0.),[Categorie("p1");Categorie("p2");Categorie("p3");Categorie("p4")]) ,
			   						[ Piece_fabriquee(Categorie("p1"),
			   								Montage([ Etape( Operation("op2", Duree(0.2), Prix(0.),[Categorie("p2")]) ,
								   						[ Piece_achetee(Categorie("p2"),Prix(80.))
								   						]
								  					  )
								  					]
								  			)
			   						  );
			   						  Piece_achetee(Categorie("p2"),Prix(80.));
			   						  Piece_fabriquee(Categorie("p3"),
			   						  		Montage([ Etape( Operation("op1", Duree(2.3), Prix(0.),[Categorie("p1");Categorie("p2")]) ,
								   						[ Piece_fabriquee(Categorie("p1"),
								   								Montage([ Etape( Operation("op2", Duree(0.2), Prix(0.),[Categorie("p2")]) ,
													   						[ Piece_achetee(Categorie("p2"),Prix(80.))
													   						]
													  					  )
													  					]
													  			)
								   						  );
								   						  Piece_achetee(Categorie("p2"),Prix(80.))
								   						]
								  					  );
								  					  Etape( Operation("op5", Duree(0.1), Prix(0.),[Categorie("p1");Categorie("p2")]) ,
								   						[ Piece_achetee(Categorie("p1"),Prix(100.));
								   						  Piece_achetee(Categorie("p2"),Prix(80.))
								   						]
								  					  )
								  					]
								  			)
			   						  );
			   						  Piece_achetee(Categorie("p4"),Prix(80.))
			   						]
			   					  )
			   					]
			   			)
			   	);
			   	Piece_fabriquee(Categorie("computer"),
			   			Montage([ Etape( Operation("complicatedoperation", Duree(4.5), Prix(0.),[Categorie("p1");Categorie("p2");Categorie("p3");Categorie("p4")]) ,
			   						[ Piece_fabriquee(Categorie("p1"),
			   								Montage([ Etape( Operation("op2", Duree(0.2), Prix(0.),[Categorie("p2")]) ,
								   						[ Piece_achetee(Categorie("p2"),Prix(80.))
								   						]
								  					  )
								  					]
								  			)
			   						  );
			   						  Piece_achetee(Categorie("p2"),Prix(80.));
			   						  Piece_fabriquee(Categorie("p3"),
			   						  		Montage([ Etape( Operation("op1", Duree(2.3), Prix(0.),[Categorie("p1");Categorie("p2")]) ,
								   						[ Piece_achetee(Categorie("p1"),Prix(100.));
								   						  Piece_achetee(Categorie("p2"),Prix(80.))
								   						]
								  					  );
								  					  Etape( Operation("op5", Duree(0.1), Prix(0.),[Categorie("p1");Categorie("p2")]) ,
								   						[ Piece_fabriquee(Categorie("p1"),
								   								Montage([ Etape( Operation("op2", Duree(0.2), Prix(0.),[Categorie("p2")]) ,
													   						[ Piece_achetee(Categorie("p2"),Prix(80.))
													   						]
													  					  )
													  					]
													  			)
								   						  );
								   						  Piece_achetee(Categorie("p2"),Prix(80.))
								   						]
								  					  )
								  					]
								  			)
			   						  );
			   						  Piece_achetee(Categorie("p4"),Prix(80.))
			   						]
			   					  )
			   					]
			   			)
			   	);
			   	Piece_fabriquee(Categorie("computer"),
			   			Montage([ Etape( Operation("complicatedoperation", Duree(4.5), Prix(0.),[Categorie("p1");Categorie("p2");Categorie("p3");Categorie("p4")]) ,
			   						[ Piece_fabriquee(Categorie("p1"),
			   								Montage([ Etape( Operation("op2", Duree(0.2), Prix(0.),[Categorie("p2")]) ,
								   						[ Piece_achetee(Categorie("p2"),Prix(80.))
								   						]
								  					  )
								  					]
								  			)
			   						  );
			   						  Piece_achetee(Categorie("p2"),Prix(80.));
			   						  Piece_fabriquee(Categorie("p3"),
			   						  		Montage([ Etape( Operation("op1", Duree(2.3), Prix(0.),[Categorie("p1");Categorie("p2")]) ,
								   						[ Piece_fabriquee(Categorie("p1"),
								   								Montage([ Etape( Operation("op2", Duree(0.2), Prix(0.),[Categorie("p2")]) ,
													   						[ Piece_achetee(Categorie("p2"),Prix(80.))
													   						]
													  					  )
													  					]
													  			)
								   						  );
								   						  Piece_achetee(Categorie("p2"),Prix(80.))
								   						]
								  					  );
								  					  Etape( Operation("op5", Duree(0.1), Prix(0.),[Categorie("p1");Categorie("p2")]) ,
								   						[ Piece_fabriquee(Categorie("p1"),
								   								Montage([ Etape( Operation("op2", Duree(0.2), Prix(0.),[Categorie("p2")]) ,
													   						[ Piece_achetee(Categorie("p2"),Prix(80.))
													   						]
													  					  )
													  					]
													  			)
								   						  );
								   						  Piece_achetee(Categorie("p2"),Prix(80.))
								   						]
								  					  )
								  					]
								  			)
			   						  );
			   						  Piece_achetee(Categorie("p4"),Prix(80.))
			   						]
			   					  )
			   					]
			   			)
			   	);
			   	
			   	(* differentes possibilites avec operation: op100 *)
			   	Piece_fabriquee(Categorie("computer"),
			   			Montage([ Etape( Operation("op100", Duree(40.), Prix(0.),[Categorie("p1");Categorie("p2");Categorie("p4")]) ,
			   						[ Piece_achetee(Categorie("p1"),Prix(100.));
			   						  Piece_achetee(Categorie("p2"),Prix(80.));
			   						  Piece_achetee(Categorie("p4"),Prix(80.))
			   						]
			  					  )
			  					]
			  			)
			   	);
			   	Piece_fabriquee(Categorie("computer"),
			   			Montage([ Etape( Operation("op100", Duree(40.), Prix(0.),[Categorie("p1");Categorie("p2");Categorie("p4")]) ,
			   						[ Piece_fabriquee(Categorie("p1"),
			   								Montage([ Etape( Operation("op2", Duree(0.2), Prix(0.),[Categorie("p2")]) ,
								   						[ Piece_achetee(Categorie("p2"),Prix(80.))
								   						]
								  					  )
								  					]
								  			)
			   						  );
			   						  Piece_achetee(Categorie("p2"),Prix(80.));
			   						  Piece_achetee(Categorie("p4"),Prix(80.))
			   						]
			  					  )
			  					]
			  			)
			   	);
			   	
			   	(* differentes possibilites *)
			   	Piece_fabriquee(Categorie("p3"),
			   			Montage([ Etape( Operation("op1", Duree(2.3), Prix(0.),[Categorie("p1");Categorie("p2")]) ,
			   						[ Piece_achetee(Categorie("p1"),Prix(100.));
			   						  Piece_achetee(Categorie("p2"),Prix(80.))
			   						]
			  					  );
			  					  Etape( Operation("op5", Duree(0.1), Prix(0.),[Categorie("p1");Categorie("p2")]) ,
			   						[ Piece_achetee(Categorie("p1"),Prix(100.));
			   						  Piece_achetee(Categorie("p2"),Prix(80.))
			   						]
			  					  )
			  					]
			  			)
			   	);
			   	Piece_fabriquee(Categorie("p3"),
			   			Montage([ Etape( Operation("op1", Duree(2.3), Prix(0.),[Categorie("p1");Categorie("p2")]) ,
			   						[ Piece_fabriquee(Categorie("p1"),
			   								Montage([ Etape( Operation("op2", Duree(0.2), Prix(0.),[Categorie("p2")]) ,
								   						[ Piece_achetee(Categorie("p2"),Prix(80.))
								   						]
								  					  )
								  					]
								  			)
			   						  );
			   						  Piece_achetee(Categorie("p2"),Prix(80.))
			   						]
			  					  );
			  					  Etape( Operation("op5", Duree(0.1), Prix(0.),[Categorie("p1");Categorie("p2")]) ,
			   						[ Piece_achetee(Categorie("p1"),Prix(100.));
			   						  Piece_achetee(Categorie("p2"),Prix(80.))
			   						]
			  					  )
			  					]
			  			)
			   	);
			   	Piece_fabriquee(Categorie("p3"),
			   			Montage([ Etape( Operation("op1", Duree(2.3), Prix(0.),[Categorie("p1");Categorie("p2")]) ,
			   						[ Piece_achetee(Categorie("p1"),Prix(100.));
			   						  Piece_achetee(Categorie("p2"),Prix(80.))
			   						]
			  					  );
			  					  Etape( Operation("op5", Duree(0.1), Prix(0.),[Categorie("p1");Categorie("p2")]) ,
			   						[ Piece_fabriquee(Categorie("p1"),
			   								Montage([ Etape( Operation("op2", Duree(0.2), Prix(0.),[Categorie("p2")]) ,
								   						[ Piece_achetee(Categorie("p2"),Prix(80.))
								   						]
								  					  )
								  					]
								  			)
			   						  );
			   						  Piece_achetee(Categorie("p2"),Prix(80.))
			   						]
			  					  )
			  					]
			  			)
			   	);
			   	Piece_fabriquee(Categorie("p3"),
			   			Montage([ Etape( Operation("op1", Duree(2.3), Prix(0.),[Categorie("p1");Categorie("p2")]) ,
			   						[ Piece_fabriquee(Categorie("p1"),
			   								Montage([ Etape( Operation("op2", Duree(0.2), Prix(0.),[Categorie("p2")]) ,
								   						[ Piece_achetee(Categorie("p2"),Prix(80.))
								   						]
								  					  )
								  					]
								  			)
			   						  );
			   						  Piece_achetee(Categorie("p2"),Prix(80.))
			   						]
			  					  );
			  					  Etape( Operation("op5", Duree(0.1), Prix(0.),[Categorie("p1");Categorie("p2")]) ,
			   						[ Piece_fabriquee(Categorie("p1"),
			   								Montage([ Etape( Operation("op2", Duree(0.2), Prix(0.),[Categorie("p2")]) ,
								   						[ Piece_achetee(Categorie("p2"),Prix(80.))
								   						]
								  					  )
								  					]
								  			)
			   						  );
			   						  Piece_achetee(Categorie("p2"),Prix(80.))
			   						]
			  					  )
			  					]
			  			)
			   	);
			   	
			   	Piece_fabriquee(Categorie("p1"),
			   			Montage([ Etape( Operation("op2", Duree(0.02), Prix(0.),[Categorie("p2")]) ,
			   						[ Piece_achetee(Categorie("p2"),Prix(80.))
			   						]
			  					  )
			  					]
			  			)
			  	)
			   ])			   	
			 );;
						